﻿using System;
using System.Collections.Generic;
using System.Management.Automation;
using CrystalDecisions.Enterprise;

namespace BO.Management.PowerShell
{
    [Cmdlet(VerbsCommon.New, "Schedule", DefaultParameterSetName = CONNECT_SECWINAD)]
    public class NewSchedule : BaseActionObject<ContentGenericProvider, CrystalDecisions.Enterprise.InfoObject>
    {

        public const Int32 DEFAULT_RETRY_INTERVAL = 1800;

        [Parameter()]
        public SwitchParameter Asynchronous { get; set; }

        [Parameter()]
        public Int32? Timeout { get; set; }

        [Parameter()]
        public Int32? NbRetry { get; set; }

        [Parameter()]
        public Int32? RetryInterval { get; set; }

        [Parameter()]
        public SwitchParameter Failure { get; set; }

        [Parameter()]
        public SwitchParameter ViewSchedule { get; set; }


        public override ContentGenericProvider GetProvider()
        {
            return new ContentGenericProvider(this.LogonProvider);
        }


        public override void WorkWithSingleObject(InfoObject boeObject)
        {

            DateTime startSchedule = DateTime.Now;

            if (boeObject == null)
            {
                this.ThrowTerminatingErrorWithExitCode(BOErrorCode.ObjectNotFound, "Report is null. It hasn't been found in the CMS");
            }


            SchedulingInfo schedulingInfo = boeObject.SchedulingInfo;
            schedulingInfo.Type = CeScheduleType.ceScheduleTypeOnce;
            schedulingInfo.RightNow = true;

            if (boeObject.Instance)
            {
                while(schedulingInfo.Dependencies.Count > 0)
                {
                    schedulingInfo.Dependencies.Delete(1);   
                    //this.ThrowTerminatingErrorWithExitCode(BOErrorCode.GenericError, "We don't know remove events so stop working...");
                }
            }


            if (this.NbRetry.HasValue)
            {
                schedulingInfo.RetriesAllowed = this.NbRetry.Value;
                schedulingInfo.RetryInterval = (this.RetryInterval.HasValue ? this.RetryInterval.Value : DEFAULT_RETRY_INTERVAL);
            }

            schedulingInfo.EndDate = schedulingInfo.BeginDate.AddHours(1);

            BoeProvider.ScheduleReport(boeObject);

            if (!this.Asynchronous)
            {
                this.QueryInstanceResult(boeObject, startSchedule);
            }
        }


        private void QueryInstanceResult(InfoObject report, DateTime scheduleStart)
        {

            this.WriteVerbose(String.Format("Start query schedule result for report {0} at {1}", report.Title, DateTime.Now));
            Boolean searchActive = true;
            while (searchActive)
            {

                if (this.Timeout.HasValue)
                {
                    if (scheduleStart.AddSeconds(this.Timeout.Value) < DateTime.Now)
                    {
                        this.ThrowTerminatingErrorWithExitCode(BOErrorCode.TimeOut,
                            String.Format("Timeout occured to retrieve the instance state for this report {0} at {1}", report.Title, DateTime.Now));
                    }
                }

                using (LogonProvider logonProvider = new LogonProvider())
                {
                    this.GetSession(logonProvider);

                    using (InstanceProvider instanceProvider = new InstanceProvider(logonProvider))
                    {
                        if (report.Instance)
                        {
                            instanceProvider.AddFilterToParent(QueryBuilder.OperatorType.Equal, report.ParentID);
                        }
                        else
                        {
                            instanceProvider.AddFilterToParent(QueryBuilder.OperatorType.Equal, report.ID);
                        }
                        instanceProvider.AddStartTime(scheduleStart);
                        List<InfoObject> results = instanceProvider.GetObject();

                        if (results == null || results.Count == 0)
                        {
                            Console.WriteLine(String.Format("Report {0} with CUID {1} has not yet created instance", report.Title, report.CUID));
                            System.Threading.Thread.Sleep(2000);
                        }
                        else
                        {
                            InfoObject result = results[0];
                            if (result.SchedulingInfo.Outcome != CeScheduleOutcome.ceOutcomePending)
                            {
                                if (result.SchedulingInfo.Outcome == CeScheduleOutcome.ceOutcomeSuccess)
                                {
                                    Console.WriteLine(String.Format("Report {0} with CUID {1} has been executed with success. End of execution at {2}", report.Title, report.CUID, DateTime.Now));
                                }
                                else
                                {
                                    this.ThrowTerminatingErrorWithExitCode(BOErrorCode.InstanceFailure,
                                        String.Format("Report {0} with CUID {1} has been executed with error.\n Error : {2}", report.Title, report.CUID, result.SchedulingInfo.ErrorMessage));

                                }
                                searchActive = false;
                            }
                            else
                            {
                                this.WriteVerbose(String.Format("Report {0} with CUID {1} is pending", report.Title, report.CUID));
                                System.Threading.Thread.Sleep(2000);
                            }
                        }
                    }
                }
            }
        }

    }

}
